﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace 经典推箱子
{
    /// <summary>
    /// 添加关卡窗体
    /// </summary>
    public partial class AddForm : Form
    {
        int no;
        /// <summary>
        /// 最多15行
        /// </summary>
        public const int ROW = 15;
        /// <summary>
        /// 最多15列
        /// </summary>
        public const int COL = 15;
        /// <summary>
        /// 用于简单显示地图
        /// </summary>
        public readonly Label[,] labels = new Label[ROW, COL];

        /// <summary>
        /// 目前用户选择的操作类型
        /// </summary>
        public string operation = "";

        public AddForm(int no)
        {
            InitializeComponent();
            //初始化标签数组
            this.Init();
            this.no = no;
            this.Text = $"添加关卡【{no}】";
            //给标签数组添加点击事件处理函数
            this.Label_Click();
        }

        /// <summary>
        /// 初始化
        /// </summary>
        private void Init()
        {
            for (int i = 0; i < ROW; i++)
            {
                for (int j = 0; j < COL; j++)
                {
                    if (labels[i, j] == null)
                    {
                        labels[i, j] = new Label();
                    }
                    Label label = labels[i, j];
                    label.BorderStyle = BorderStyle.Fixed3D;
                    label.ForeColor = Color.Black;
                    label.Visible = true;
                    label.AutoSize = false;
                    label.Size = new Size(30, 30);
                    label.Location = new Point(j * labels[i, j].Size.Width, i * labels[i, j].Size.Height);
                    label.BackColor = Color.Black;
                    label.TextAlign = ContentAlignment.MiddleCenter;
                    label.Font = new Font("楷体", 12f);
                    label.Tag = 0;
                    panel.Controls.Add(label);
                }
            }
        }

        private void 墙壁ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "墙";
            this.toolStripLabel.Text = "当前操作【墙壁】";
        }

        private void 箱子ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "箱";
            this.toolStripLabel.Text = "当前操作【箱子】";
        }

        private void 目标ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "〇";
            this.toolStripLabel.Text = "当前操作【目标】";
        }

        private void 完成ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "×";
            this.toolStripLabel.Text = "当前操作【箱标】";
        }

        private void 主角ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "人";
            this.toolStripLabel.Text = "当前操作【主角】";
        }

        private void 进标ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "囚";
            this.toolStripLabel.Text = "当前操作【人标】";
        }

        private void 抹杀ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "";
            this.toolStripLabel.Text = "当前操作【抹杀】";
        }

        private void 清空ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.operation = "";
            if (MessageBox.Show("是否清空本次布局", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning) == DialogResult.OK)
            {
                for (int i = 0; i < ROW; i++)
                {
                    for (int j = 0; j < COL; j++)
                    {
                        Label label = labels[i, j];
                        label.BorderStyle = BorderStyle.Fixed3D;
                        label.BackColor = Color.Black;
                        label.Text = "";
                        label.Tag = 0;
                    }
                }
            }
        }

        /// <summary>
        /// 点击标签，将目前操作加到此控件中
        /// 添加元素，或抹杀元素
        /// </summary>
        private void Label_Click()
        {
            for (int i = 0; i < ROW; i++)
            {
                for (int j = 0; j < COL; j++)
                {
                    Label label = labels[i, j];
                    label.Click += (sender, e) =>
                    {
                        Debug.WriteLine(this.operation);
                        label.Text = this.operation;
                        label.Tag = 0;
                        switch (this.operation)
                        {
                            case "":
                                label.BackColor = Color.Black;
                                label.Tag = 0;
                                break;
                            case "墙":
                                label.BackColor = Color.White;
                                label.Tag = 1;
                                break;
                            case "箱":
                                label.BackColor = Color.Blue;
                                label.Tag = 2;
                                break;
                            case "〇":
                                label.BackColor = Color.Yellow;
                                label.Tag = 3;
                                break;
                            case "×":
                                label.BackColor = Color.Green;
                                label.Tag = 5;
                                break;
                            case "人":
                                label.Tag = 6;
                                label.BackColor = Color.Red;
                                break;
                            case "囚":
                                label.Tag = 9;
                                label.BackColor = Color.Red;
                                break;
                        }
                    };
                }
            }
        }

        /// <summary>
        /// 注意保存主要内容，即把地图四周的多余空格去掉
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void 保存ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                //使用四周向中间扩张法，把没用的空白地方去掉
                //是否无效
                bool[,] flag = new bool[ROW, COL];
                //是否已访问
                bool[,] visit = new bool[ROW, COL];

                //四周边界向内扩散
                for (int i = 0, j = 0; j < COL; j++)
                {
                    KuoSan(flag, visit, i, j);
                }
                for (int i = ROW - 1, j = 0; j < COL; j++)
                {
                    KuoSan(flag, visit, i, j);
                }
                for (int i = 0, j = 0; i < ROW; i++)
                {
                    KuoSan(flag, visit, i, j);
                }
                for (int i = 0, j = COL - 1; i < ROW; i++)
                {
                    KuoSan(flag, visit, i, j);
                }

                //把有效的各个点记录到新关卡中
                List<Block> blocks = new List<Block>();
                for (int i = 0; i < ROW; i++)
                {
                    for (int j = 0; j < COL; j++)
                    {
                        //该点无效
                        if (flag[i, j])
                        {
                            continue;
                        }

                        blocks.Add(new Block()
                        {
                            X = i,
                            Y = j,
                            Type = (BlockType)labels[i, j].Tag
                        });
                    }
                }

                if (blocks.Count == 0)
                {
                    MessageBox.Show("地图为空，无法保存","提示",MessageBoxButtons.OK,MessageBoxIcon.Error);
                    return;
                }

                //存储前把坐标都移动到左上角，方便取关卡时可以轻松把它放到地图中央
                int minX = blocks.Min(item => item.X);
                int minY = blocks.Min(item => item.Y);
                foreach (var item in blocks)
                {
                    item.X -= minX;
                    item.Y -= minY;
                }

                //保存
                StringBuilder sb = new StringBuilder();
                foreach (var item in blocks)
                {
                    sb.Append(item.X);
                    sb.Append(',');
                    sb.Append(item.Y);
                    sb.Append(',');
                    sb.Append((int)item.Type);
                    sb.Append('\n');
                }
                //保存到Level文件夹中
                while (File.Exists($"Level/{no}.level"))
                {
                    no++;
                }
                File.WriteAllText($"Level/{no}.level", sb.ToString());
                MessageBox.Show("保存成功，关闭窗体","提示",MessageBoxButtons.OK,MessageBoxIcon.Information);
                this.Close();
            }
            catch (Exception exception)
            {
                MessageBox.Show(exception.Message,"提示",MessageBoxButtons.OK,MessageBoxIcon.Error);
            }
        }

        /// <summary>
        /// 扩散法
        /// </summary>
        private void KuoSan(bool[,] flag, bool[,] visit, int i, int j)
        {
            //点不合法
            if (i < 0 || j < 0 || i >= ROW || j >= COL)
            {
                return;
            }

            //已访问过该点
            if (visit[i, j])
            {
                return;
            }

            //标记为已访问
            visit[i, j] = true;

            //无效空地
            if (this.labels[i, j].Text == "")
            {
                flag[i, j] = true;
                KuoSan(flag, visit, i - 1, j);
                KuoSan(flag, visit, i + 1, j);
                KuoSan(flag, visit, i, j - 1);
                KuoSan(flag, visit, i, j + 1);
            }
        }
    }
}
